package com.x.mvp.base.exlist;

import android.database.DataSetObserver;
import android.view.View;
import android.view.ViewStub;
import android.widget.AbsListView;
import android.widget.ListView;

import com.x.mvp.R;
import com.x.mvp.base.view.pulltorefresh.PullToRefreshFragmentView;
import com.x.mvp.widget.stickyexpandable.ExpandableStickyListHeadersListView;
import com.x.mvp.widget.stickyexpandable.StickyListHeadersAdapter;

import in.srain.cube.views.ptr.PtrFrameLayout;


public abstract class PullToRefreshListViewFragmentView<P extends PullToRefreshRecyclerPresenter> extends PullToRefreshFragmentView<P> {

    private static final int ITEM_LEFT_TO_LOAD_MORE = 20;
    private ExpandableStickyListHeadersListView listView;
    private ViewStub moreProgress;
    private View moreProgressView;
    private boolean isLoadingMore;
    private int moreProgressId;

    protected AbsListView.OnScrollListener internalOnScrollListener;
    protected AbsListView.OnScrollListener externalOnScrollListener;

    protected int getRecyclerViewID() {
        return R.id.list_view;
    }

    protected int getMoreProgressViewID() {
        return R.layout.more_progress;
    }

    public ExpandableStickyListHeadersListView getListView() {
        return listView;
    }

    @Override
    protected int getPullMode() {
        return PULL_MODE_REFRESH_LOADMORE;
    }

    @Override
    protected void initView() {
        super.initView();
        if (listView == null) {
            if (getPullMode() == PULL_MODE_REFRESH_LOADMORE) {
                this.moreProgressId = getMoreProgressViewID();
                moreProgress = (ViewStub) mainView.findViewById(R.id.more_progress);
                moreProgress.setLayoutResource(moreProgressId);
                if (moreProgressId != 0) {
                    moreProgressView = moreProgress.inflate();
                }
                hideMoreProgress();
            }

            this.initListView(mainView);
            this.customizeListView();
            this.setAdapter(getAdapter());
        }
        loadData();
    }

    public void loadData() {
        presenter.loadData();
    }

    public void reloadData() {
        presenter.reloadData();
    }

    @Override
    public void onDestroyView() {
        getPtrFrameLayout().refreshComplete();
        super.onDestroyView();
    }

    private void initListView(View view) {
        View listView = view.findViewById(getRecyclerViewID());
        if (listView instanceof ExpandableStickyListHeadersListView) {
            this.listView = (ExpandableStickyListHeadersListView) listView;
        } else {
            throw new IllegalArgumentException(getClass().getSimpleName() + " can't work without a ListView!");
        }

        if (this.listView != null) {

            internalOnScrollListener = new ListView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(AbsListView absListView, int i) {
                    if (externalOnScrollListener != null) {
                        externalOnScrollListener.onScrollStateChanged(absListView, i);
                    }
                }

                @Override
                public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

                    if (getPullMode() == PULL_MODE_REFRESH_LOADMORE) {
                        processOnMore(firstVisibleItem, visibleItemCount, totalItemCount);
                    }
                    if (externalOnScrollListener != null) {
                        externalOnScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
                    }
                }
            };
            this.listView.setOnScrollListener(internalOnScrollListener);
            this.listView.setDivider(null);
        }
    }

    public void refreshComplete() {
        getPtrFrameLayout().refreshComplete();
    }

    private boolean haveMore() {
        return presenter.hasMoreData();
    }

    private void processOnMore(int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        int lastVisibleItemPosition = firstVisibleItem + visibleItemCount;
        if (((totalItemCount - lastVisibleItemPosition) == 0 && totalItemCount > visibleItemCount)
                && !isLoadingMore) {
            if (haveMore()) {
                showMoreProgress();
                setLoadingMore(true);
                loadMore(totalItemCount);
            } else {
                hideMoreProgress();
                setLoadingMore(false);
            }
        }
    }

    @Override
    public void onRefreshBegin(PtrFrameLayout frame) {
        presenter.reloadData();
    }


    private void setAdapterInternal(StickyListHeadersAdapter adapter) {
        if (listView != null) {
            listView.setAdapter(adapter);
        }

        if (adapter != null && getPullMode() == PULL_MODE_REFRESH_LOADMORE) {
            adapter.registerDataSetObserver(new DataSetObserver() {
                @Override
                public void onChanged() {
                    super.onChanged();
                    onUpdated();
                }

                @Override
                public void onInvalidated() {
                    super.onInvalidated();
                    onUpdated();
                }

                private void onUpdated() {
                    hideMoreProgress();
                    isLoadingMore = false;
                }
            });
        }

    }

    protected void customizeListView() {
    }

    protected abstract StickyListHeadersAdapter getAdapter();

    protected void loadMore(int totalItemCount) {
        presenter.loadMore(totalItemCount);
    }

    public void setAdapter(StickyListHeadersAdapter adapter) {
        setAdapterInternal(adapter);
    }

    public void setOnScrollListener(ListView.OnScrollListener listener) {
        externalOnScrollListener = listener;
    }

    public boolean isLoadingMore() {
        return isLoadingMore;
    }

    public void setLoadingMore(boolean isLoadingMore) {
        this.isLoadingMore = isLoadingMore;
    }

    public View getMoreProgressView() {
        return moreProgressView;
    }

    public void showMoreProgress() {
        if (moreProgress != null) {
            moreProgress.setVisibility(View.VISIBLE);
        }
    }

    public void hideMoreProgress() {
        if (moreProgress != null) {
            moreProgress.setVisibility(View.GONE);
        }
    }

    public void showLoadMoreFinished() {
        hideMoreProgress();
        isLoadingMore = false;
    }
}
